package ArrayProblems;

import java.lang.reflect.Array;
import java.util.*;

/**
 * 697. 数组的度
 * 给定一个非空且只包含非负数的整数数组 nums, 数组的度的定义是指数组里任一元素出现频数的最大值。
 *
 * 你的任务是找到与 nums 拥有相同大小的度的最短连续子数组，返回其长度。
 *
 * 示例 1:
 *
 * 输入: [1, 2, 2, 3, 1]
 * 输出: 2
 * 解释:
 * 输入数组的度是2，因为元素1和2的出现频数最大，均为2.
 * 连续子数组里面拥有相同度的有如下所示:
 * [1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
 * 最短连续子数组[2, 2]的长度为2，所以返回2.
 * 示例 2:
 *
 * 输入: [1,2,2,3,1,4,2]
 * 输出: 6
 * 注意:
 *
 * nums.length 在1到50,000区间范围内。
 * nums[i] 是一个在0到49,999范围内的整数。
 */
public class findShortestSubArray {
    /**
     * 方法一：定义一个MAP,用于定义每个元素在数组中出现的频率，然后存储最大的数，在最大的数中寻找最小的度即可
     * @param nums 输入数组
     * @return ShortestSubArray
     */
    public int findShortestSubArray(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        Map<Integer, Integer> map = new TreeMap<>();
        for (int i : nums) {
            map.put(i, map.getOrDefault(i, 0) + 1);
        }
        int maxCount = Integer.MIN_VALUE;
        List<Integer> resNumList = new ArrayList<>();
        for (int key : map.keySet()) {
            if (map.get(key) > maxCount) {
                maxCount = map.get(key);
                resNumList.clear();
                resNumList.add(key);
            } else if (map.get(key) == maxCount) {
                resNumList.add(key);
            } else {
                continue;
            }
        }
        int minRes = Integer.MAX_VALUE;
        for (int resNum : resNumList) {
            int tempRes = findMinRangeOfNum(resNum, nums);
            if (tempRes < minRes) {
                minRes = tempRes;
            }
        }
        return minRes;
    }

    private int findMinRangeOfNum(int num, int[] nums) {
        int l = 0;
        int h = nums.length - 1;
        for (int i = 0; i <= nums.length - 1; i++) {
            if (nums[i] == num) {
                l = i;
                break;
            }
        }
        for (int i = nums.length - 1; i >= 0; i--) {
            if (nums[i] == num) {
                h = i;
                break;
            }
        }
        return h - l + 1;
    }
}

class findShortestSubArrayI {
    private Map<Integer, Element> map = new HashMap<>();

    public int findShortestSubArray(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int maxFrequency = Integer.MIN_VALUE;
        for (int i = 0; i < nums.length; i++) {
            Element element = map.getOrDefault(nums[i], new Element());
            element.Frequency += 1;
            element.minIndex = Math.min(i, element.minIndex);
            element.maxIndex = Math.max(i, element.maxIndex);
            element.corRes = element.maxIndex - element.minIndex + 1;
            map.put(nums[i], element);
            if (element.Frequency > maxFrequency) {
                maxFrequency = element.Frequency;
            }
        }
        int res = Integer.MAX_VALUE;
        for (int key : map.keySet()) {
            Element element = map.get(key);
            if (element.Frequency == maxFrequency) {
                if (element.corRes < res) {
                    res = element.corRes;
                }
            }
        }
        return res;
    }

    class Element {
        int Frequency = 0;
        int minIndex = Integer.MAX_VALUE;
        int maxIndex = Integer.MIN_VALUE;
        int corRes = 0;
    }
}
